package cn.net.autocode.platform.auth;

import cn.hutool.captcha.CaptchaUtil;
import cn.hutool.captcha.LineCaptcha;
import cn.hutool.core.util.DesensitizedUtil;
import cn.hutool.core.util.StrUtil;
import cn.net.autocode.core.bean.ResultT;
import cn.net.autocode.core.utils.ClientIpUtils;
import cn.net.autocode.core.utils.JwtUtils;
import cn.net.autocode.core.utils.PasswordUtils;
import cn.net.autocode.core.utils.UserThreadLocalUtils;
import cn.net.autocode.dbManager.Dao;
import cn.net.autocode.platform.auth.service.PlatformAuthServ;
import cn.net.autocode.platform.cache.AutoCacheUtil;
import cn.net.autocode.platform.config.PlatformConfig;
import cn.net.autocode.platform.config.SpringProfileConfig;
import cn.net.autocode.platform.constants.PlatformConstant;
import cn.net.autocode.platform.entrance.MenuEntrance;
import cn.net.autocode.platform.security.service.SecurityServ;
import cn.net.autocode.platform.viewEngine.AutoCodeThymeleaf;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.View;
import org.thymeleaf.templateresource.ClassLoaderTemplateResource;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;


@Slf4j
@Controller
@RequestMapping("/platform")
public class PlatformAuth {

    private final Dao dao;

    private final AutoCacheUtil cacheUtil;

    private final SpringProfileConfig profileConfig;

    private final PlatformAuthServ authServ;

    private final SecurityServ securityServ;


    public PlatformAuth(Dao dao, AutoCacheUtil cacheUtil, SpringProfileConfig profileConfig, PlatformAuthServ authServ, SecurityServ securityServ) {
        this.dao = dao;
        this.cacheUtil = cacheUtil;
        this.profileConfig = profileConfig;
        this.authServ = authServ;
        this.securityServ = securityServ;

    }

    @RequestMapping(value = "/randomImage/{key}", produces = MediaType.IMAGE_PNG_VALUE)
    public ResponseEntity<byte[]> randomImage(@PathVariable String key) throws IOException {
        LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(130, 40, 4, 4);

        // 获取验证码的文本
        String code = lineCaptcha.getCode().toLowerCase();
        cacheUtil.setRandomImage(key,code);

        // 获取验证码的图片
        BufferedImage image = lineCaptcha.getImage();

        // 将BufferedImage转换为字节数组
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ImageIO.write(image, "png", bos);
        byte[] bytes = bos.toByteArray();

        // 关闭流
        bos.close();

        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
        headers.add("file-name", URLEncoder.encode(key+".png", StandardCharsets.UTF_8));
        headers.setContentDispositionFormData("attachment", URLEncoder.encode(key+".png", StandardCharsets.UTF_8));
        return new ResponseEntity<>(bytes, headers, HttpStatus.OK);

    }

    /**
     * 页面登录
     */
    @PostMapping(value = "/login", produces = "application/json;charset=UTF-8")
    @ResponseBody
    public ResultT login(@RequestBody JSONObject sysLoginModel, HttpServletRequest request) {
        if (sysLoginModel.isEmpty()) {
            return ResultT.fail("登录失败！");
        }

        String account = sysLoginModel.getString("account");
        String password = sysLoginModel.getString("password");

        JSONObject rs = authServ.accountLogin(account,password,"N");

        if(rs.getIntValue("code")==1){
            String clientIp = ClientIpUtils.getIpAddr(request);
            String lastLoginOrg = rs.getString("lastLoginOrg");
            String username = rs.getString("username");
            authServ.loginLog(username,clientIp,lastLoginOrg,"N");
            return ResultT.success(rs);
        }else if(rs.getIntValue("code")==2){
            return ResultT.success(rs);
        }else{
            return ResultT.fail(rs.getString("msg"));
        }
    }

    /**
     * 页面登录
     */
    @ResponseBody
    @PostMapping(value = "/relogin", produces = "application/json;charset=UTF-8")
    public ResultT relogin(HttpServletRequest request, @RequestBody JSONObject sysLoginModel) {

        if (sysLoginModel.isEmpty()) {
            return ResultT.fail("用户名或密码错误！");
        }

        String username = sysLoginModel.getString("username");
        String password = sysLoginModel.getString("password");

        String token = request.getHeader(PlatformConfig.tokenKey);
        String tokenusername = JwtUtils.getUsername(token);
        if (!username.equals(tokenusername)) {
            return ResultT.fail("用户名或密码错误");
        }

        JSONObject rs = authServ.tokenReLogin(username, password,"N");
        if(rs.getIntValue("code")==1){
            String clientIp = ClientIpUtils.getIpAddr(request);
            String lastLoginOrg = rs.getString("lastLoginOrg");
            authServ.loginLog(username,clientIp,lastLoginOrg,"N");
            return ResultT.success(rs);
        }else if(rs.getIntValue("code")==2){
            String newToken = rs.getString("token");
            cacheUtil.delToken(newToken,"N");
            return ResultT.success(rs);
        }
        else{
            return ResultT.fail(rs.getString("msg"));
        }
    }

    /**
     * 页面登录
     */
    @ResponseBody
    @PostMapping(value = "/checkToken", produces = "application/json;charset=UTF-8")
    public ResultT checkToken() {
        JSONObject rs = new JSONObject();
        rs.put("userName", UserThreadLocalUtils.getUserName());
        rs.put("realName", UserThreadLocalUtils.getRealName());
        rs.put("orgName", UserThreadLocalUtils.getOrgName());
        rs.put("email", UserThreadLocalUtils.getEmail());
        rs.put("phone", DesensitizedUtil.mobilePhone(UserThreadLocalUtils.getPhone()));
        rs.put("orgCode",UserThreadLocalUtils.getOrgCode());
        rs.put("deptList", UserThreadLocalUtils.getDeptList());
        if(StrUtil.isBlank(UserThreadLocalUtils.getOrgCode())){
            return ResultT.fail("token无效，请重新登录！");
        }
        return ResultT.success(rs);
    }

    /**
     * 进入页面登录
     * 2022-6-17
     */
    @RequestMapping(value = "/forLogin")
    public String forLogin(HttpServletRequest request) {
        this.titleSet(request);
        return PlatformConstant.LOGIN_VIEW;
    }

    /**
     * 退出登录
     */
    @RequestMapping(value = "/logout",produces = "application/json;charset=UTF-8")
    @ResponseBody
    public ResultT logout(HttpServletRequest request) {
        String token = request.getHeader(PlatformConfig.tokenKey);
        if (StrUtil.isBlank(token)) {
            return ResultT.success().msg("退出登录成功！");
        }
        String clientIp = ClientIpUtils.getIpAddr(request);
        cacheUtil.delToken(token,"N");
        authServ.logoutLog(token,"N",clientIp);
        return ResultT.success().msg("退出登录成功！");
    }

    @ResponseBody
    @RequestMapping(value = "/modifySelfPasswrd")
    public ResultT modifySelfPasswrd(@RequestBody JSONObject param) {
        String password = param.getString("password");
        if(!securityServ.checkPassword(password)){
            return ResultT.fail("原密码错误！");
        }
        String newpasswrd = param.getString("newpasswrd");
        String confirmpasswrd = param.getString("confirmpasswrd");
        if (!newpasswrd.equals(confirmpasswrd)){
            return ResultT.fail("两次密码不一致！");
        }

        String rs = securityServ.checkPasswordValidate(newpasswrd);
        if(!"success".equals(rs)){
            return ResultT.fail(rs);
        }

        String hashed = PasswordUtils.hashpw(newpasswrd);
        dao.executeUpdate("update sys_users set passwrd =? where username=?",hashed,UserThreadLocalUtils.getUserName());
        return ResultT.success();
    }


    /**
     * 页面登录
     */
    @ResponseBody
    @PostMapping(value = "/loginOrgan/{orgCode}", produces = "application/json;charset=UTF-8")
    public ResultT loginOrgan(@PathVariable("orgCode") String orgCode,HttpServletRequest request) {
        String userName = UserThreadLocalUtils.getUserName();
        String token = UserThreadLocalUtils.getToken();
        JSONObject organ = dao.queryJSON("select t1.label,t1.code from sys_organ t1,sys_organ_users t2 where t1.code=t2.org_code and t2.username=? and t2.org_code=?",userName,orgCode);
        if(organ.isEmpty()){
            cacheUtil.delToken(token,"N");
            return ResultT.fail("您没有访问该组织的权限！");
        }else {
            JSONObject sysUser = cacheUtil.getTokenUser(token,"N");
            sysUser.put("orgCode",orgCode);
            sysUser.put("orgName",organ.getString("label"));

            String sql = "select t1.dept label,t1.id value from sys_departments t1,sys_department_user t2 where t1.id=t2.dept_id and t1.org_code=? and t2.username=?";
            JSONArray deptList = dao.queryJSONArray(sql,orgCode,userName);
            sysUser.put("deptList", deptList);

            cacheUtil.setToken(token,sysUser,"N");
            dao.executeUpdate("update sys_users set last_login_org=? where username=?",orgCode,userName);
            String clientIp = ClientIpUtils.getIpAddr(request);
            authServ.loginLog(userName,clientIp,orgCode,"N");
            return ResultT.success();
        }
    }

    /**
     * 页面登录
     */
    @ResponseBody
    @PostMapping(value = "/changeOrgan/{orgCode}", produces = "application/json;charset=UTF-8")
    public ResultT changeOrgan(@PathVariable("orgCode") String orgCode) {
        String userName = UserThreadLocalUtils.getUserName();
        String token = UserThreadLocalUtils.getToken();
        JSONObject organ = dao.queryJSON("select t1.label,t1.code from sys_organ t1,sys_organ_users t2 where t1.code=t2.org_code and t2.username=? and t2.org_code=?",userName,orgCode);
        if(organ.isEmpty()){
            return ResultT.fail("您没有访问该组织的权限！");
        }else {
            JSONObject sysUser = cacheUtil.getTokenUser(token,"N");
            sysUser.put("orgCode",orgCode);
            sysUser.put("orgName",organ.getString("label"));
            cacheUtil.setToken(token,sysUser,"N");
            dao.executeUpdate("update sys_users set last_login_org=? where username=?",orgCode,userName);
            return ResultT.success();
        }
    }


    /**
     * 系统主页面
     */
    @RequestMapping(value = "main")
    public ModelAndView index() {
        String projectName = dao.queryValue("select project_name from autocode_platform",String.class);
        if(StrUtil.isBlank(projectName)){
            projectName = "AutoCode";
        }
        ModelAndView mav = new ModelAndView();

        mav.addObject("mode",profileConfig.getProfile());
        mav.addObject("title",projectName);
        mav.addObject("projectName",projectName);

        try {
            ClassLoaderTemplateResource resource = new ClassLoaderTemplateResource("templates/platform/main.html","UTF-8");
            if(resource.exists()){
                mav.setViewName("/platform/main");
            }else{
                ClassLoader classLoader = MenuEntrance.class.getClassLoader();
                InputStream inputStream = classLoader.getResourceAsStream("html/platform/main.html");
                byte[] bytes = new byte[0];
                if (inputStream != null) {
                    bytes = inputStream.readAllBytes();
                }
                String html = new String(bytes);
                View view = new AutoCodeThymeleaf(html);
                mav.setView(view);
            }
        } catch (IOException e) {
            //throw new RuntimeException(e);
        }
        return mav;
    }

    /**
     * 进入手机注册页面
     */
    @RequestMapping(value = "/phoneRegister")
    public String phoneRegister(HttpServletRequest request) {
        this.titleSet(request);
        return "/platform/phoneRegister";
    }


    /**
     * 进入邮箱注册页面
     */
    @RequestMapping(value = "/emailRegister")
    public String emailRegister(HttpServletRequest request) {
        this.titleSet(request);
        return "/platform/emailRegister";
    }

    /**
     * 注册成功提示
     * 2022-6-17
     */
    @RequestMapping(value = "/registerSuccess")
    public String registerSuccess(HttpServletRequest request) {
        this.titleSet(request);
        return "/platform/registerSuccess";
    }

    /**
     * 进入更改密码页面
     * 2022-6-17
     */
    @RequestMapping(value = "/retrievePassword")
    public String retrievePassword(HttpServletRequest request) {
        this.titleSet(request);
        return "/platform/retrievePassword";
    }

    /**
     * 进入更改密码页面
     * 2022-6-17
     */
    @RequestMapping(value = "/phoneRetrievePassword")
    public String phoneRetrievePassword(HttpServletRequest request) {
        this.titleSet(request);
        return "/platform/phoneRetrievePassword";
    }

    /**
     * 显示用户协议
     */
    @RequestMapping(value = "/showXieYi")
    public String showXieYi(HttpServletRequest request) {
        this.titleSet(request);
        return "/platform/xieyi";
    }

    /**
     * 操作成功
     */
    @RequestMapping(value = "/operSuccess")
    public String operSuccess(HttpServletRequest request) {
        this.titleSet(request);
        return "/platform/operSuccess";
    }

    private void titleSet(HttpServletRequest request){
        //获取项目名称
        String projectName = dao.queryValue("select project_name from autocode_platform",String.class);
        if(StrUtil.isBlank(projectName)){
            projectName = "AutoCode";
        }
        request.setAttribute("title",projectName);
        request.setAttribute("projectName",projectName);
    }

}
